package com.iknowone.db;

import java.net.UnknownHostException;
import java.util.Arrays;
import org.apache.log4j.Logger;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;


/**
 * Class that initializes and provides access methods to the mongo database.
 * 
 * @author Adriana
 * @version $Revision: 111 $
 */
public class MongoConnector {
    private static final Logger LOGGER = Logger.getLogger(MongoConnector.class);
    private static final MongoConnector UNIQUE_INSTANCE = new MongoConnector();
    
    private MongoClient mongoClient;
    private DB mongo;
    private String databaseName = "iknowone";
    private int connectionsPerHost= 100;
    private int connectionTimeout = 5000;
    private int maxWaitTime = 5000;
    private int socketTimeout = 5000;
    private int threadsAllowedToBlockForConnectionMultiplier = 10;
    private String host = "localhost";
    private int port = 27017;
    private String username = "iknowone";
    private String password = "iknowone";
    
    
    private MongoConnector(){
    	try {
            MongoCredential credentials = MongoCredential
                    .createMongoCRCredential(username,databaseName, 
                            password.toCharArray());
            MongoClientOptions options = new MongoClientOptions.Builder()
                            .connectionsPerHost(connectionsPerHost)
                            .connectTimeout(connectionTimeout)
                            .maxWaitTime(maxWaitTime)
                            .socketTimeout(socketTimeout)
                            .threadsAllowedToBlockForConnectionMultiplier(
                                    threadsAllowedToBlockForConnectionMultiplier)
                            .build();
            mongoClient = new MongoClient(new ServerAddress(host, port), 
                    Arrays.asList(credentials), options);
            mongo = mongoClient.getDB(databaseName);
            if (mongo == null) {
                throw new ExceptionInInitializerError("Failed to get database "
                        + databaseName);
            }
        } catch (UnknownHostException e) {
            LOGGER.error("Failed to initialize mongo client " + host + " : "
                    + port);
            throw new ExceptionInInitializerError(e);
        }
    };
    
    public static MongoConnector getInstance() {
        return UNIQUE_INSTANCE;
    }
    
    public void init() {
        
    }
   
    /**
     * Obtain the database with which the system works with.
     * 
     * @return an object of type {@code DB} containing the database object
     */
    public DB getDatabase() {
        return mongo;
    }

    /**
     * Get the collection with the specified name.
     * 
     * @param collectionName the collection name to return
     * @return an object of type {@code DBCollection} containing the collection
     * object with the specified name
     */
    public DBCollection getCollection(String collectionName) {
        return mongo.getCollection(collectionName);
    }

    /**
     * Closes the mongo client. Mongo client is only one instance per system,
     * this should be closed only once when the system shuts down.
     */
    void closeConnection() {
        if (mongoClient != null) {
            mongoClient.close();
        }
    }

    public String getDatabaseName() {
        return databaseName;
    }

    public int getConnectionsPerHost() {
        return connectionsPerHost;
    }

    public int getConnectionTimeout() {
        return connectionTimeout;
    }

    public int getMaxWaitTime() {
        return maxWaitTime;
    }

    public int getSocketTimeout() {
        return socketTimeout;
    }

    public int getThreadsAllowedToBlockForConnectionMultiplier() {
        return threadsAllowedToBlockForConnectionMultiplier;
    }

    public String getHost() {
        return host;
    }

    public int getPort() {
        return port;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public void setDatabaseName(String databaseName) {
        this.databaseName = databaseName;
    }

    public void setConnectionsPerHost(int connectionsPerHost) {
        this.connectionsPerHost = connectionsPerHost;
    }

    public void setConnectionTimeout(int connectionTimeout) {
        this.connectionTimeout = connectionTimeout;
    }

    public void setMaxWaitTime(int maxWaitTime) {
        this.maxWaitTime = maxWaitTime;
    }

    public void setSocketTimeout(int socketTimeout) {
        this.socketTimeout = socketTimeout;
    }

    public void setThreadsAllowedToBlockForConnectionMultiplier(
            int threadsAllowedToBlockForConnectionMultiplier) {
        this.threadsAllowedToBlockForConnectionMultiplier =
                threadsAllowedToBlockForConnectionMultiplier;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
